# coding: utf-8

from __future__ import absolute_import, division, print_function, unicode_literals

import configparser
import os
import sys
from enum import Enum
from pathlib import Path

import pytomlpp
import yaml

from apitest import att_repo, main_repo
from apitest.engine.const.model import ApiTTConfig
from apitest.engine.logging import logger


class ConfigParse(configparser.RawConfigParser):
    """
    框架中底层所使用的方法，业务一般不建议使用，解析器，用于解析config文件
    """

    def __init__(self, defaults=None):
        configparser.RawConfigParser.__init__(self, defaults=defaults)

    def optionxform(self, optionstr):
        return optionstr


class ConfigType(Enum):
    ini = 'ini'
    yaml = 'yaml'
    toml = 'toml'


class Config:

    def __init__(self, filename, repo_path=None):
        self.filename = filename
        if not repo_path:
            repo_path = os.getcwd()
            file = os.path.join(repo_path, "conf", self.filename)
            if not os.path.exists(file):
                p = Path(sys.path[0])
                repo_path = p.resolve()
                file = os.path.join(repo_path, "conf", self.filename)
                while not os.path.exists(file):
                    repo_path = repo_path.parent
                    file = os.path.join(repo_path, "conf", self.filename)
                    if os.path.exists(file):
                        break

        self.path = os.path.join(repo_path, "conf", self.filename)
        suffix = self.filename.split('.')
        if len(suffix) < 2:
            raise Exception("请指定文件类型")
        self.type = suffix[-1]

    def get_conf(self, *args, obj=None):

        if self.type == ConfigType.ini.value:
            dit = self._read_ini()
        elif self.type == ConfigType.yaml.value:
            dit = self._read_yaml()
        elif self.type == ConfigType.toml.value:
            dit = self._read_toml()
        else:
            raise Exception("文件类型为: %s, 暂不支持" % self.type)
        dit = self._get_value(dit, *args)
        logger.info("Get %s config from %s, value: %s" % ("->".join(args), self.filename, dit))
        if obj:
            return obj(**dit)
        return dit

    def _read_ini(self):
        cf = ConfigParse()
        cf.read(self.path)
        return dict(getattr(cf, "_sections"))

    def _read_yaml(self):
        with open(self.path) as f:
            config = yaml.safe_load(f.read())
            f.close()
            return config

    def _read_toml(self):
        cf = pytomlpp.load(str(self.path))
        return cf

    @staticmethod
    def _get_value(dit, *args):
        try:
            for i in args:
                dit = dit[i]
            return dit
        except KeyError as e:
            raise KeyError("key: {} not in dict: {}".format(e, dit))


class ConfigV2:
    """
    读取config.yaml文件，文件放在项目根目录下
    """

    def __init__(self, config_dir, filename="config.yaml"):
        """
        :param config_dir: 配置文件目录
        :param filename: 配置文件名
        """
        self.file = os.path.join(config_dir, filename)

    def get_config(self):
        with open(self.file) as f:
            data = yaml.safe_load(f)
            ApiTTConfig.Config.use_enum_values = False
            config = ApiTTConfig(**data)
            f.close()
        return config


main_config = ConfigV2(config_dir=main_repo).get_config()
att_config = ConfigV2(config_dir=att_repo).get_config()
